/**
 * @file hrt_call.h
 * 
 * High Resolution Timer (HRT) callout interface for FreeRTOS
 * 
 * This module provides microsecond-precision timer callbacks compatible with PX4's hrt_call API.
 * It uses FreeRTOS software timers as the underlying implementation.
 * 
 * Key features:
 * - Microsecond-precision absolute time (hrt_abstime)
 * - One-shot timers (hrt_call_after, hrt_call_at)
 * - Periodic timers (hrt_call_every)
 * - Timer cancellation (hrt_cancel)
 * - Thread-safe operations
 * 
 * @note Callbacks run in timer task context, so they should be short and non-blocking
 */

#pragma once

#include "px4_platform_common/defines.h"
#include <stdint.h>
#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @brief Absolute time in microseconds
 * 
 * Absolute time is measured from system startup and should never wrap or go backwards.
 * This provides a 64-bit microsecond counter that can run for ~584,000 years.
 */
typedef uint64_t hrt_abstime;

/**
 * @brief Callout function type
 * 
 * @param arg User-provided argument passed to the callback
 * 
 * @note Callbacks run in the FreeRTOS timer task context and must not block.
 *       Keep callbacks short and avoid calling blocking functions.
 */
typedef void (*hrt_callout)(void *arg);

/**
 * @brief Callout record structure
 * 
 * This structure represents a timer callout. Users should treat this as opaque
 * and initialize it with hrt_call_init() before use.
 */
typedef struct hrt_call {
    TimerHandle_t timer;        /**< FreeRTOS timer handle */
    hrt_abstime deadline;       /**< Absolute time when callback should fire (microseconds) */
    hrt_abstime period;         /**< Period for repeating timers (0 for one-shot) */
    hrt_callout callout;        /**< User callback function */
    void *arg;                  /**< User argument for callback */
    bool active;                /**< True if timer is currently scheduled */
} hrt_call_t;

/**
 * @brief Get absolute time in microseconds
 * 
 * Returns a monotonically increasing timestamp in microseconds since system startup.
 * This function is thread-safe and can be called from any context.
 * 
 * @return Current absolute time in microseconds
 */
hrt_abstime hrt_absolute_time(void);

/**
 * @brief Store absolute time in an interrupt-safe manner
 * 
 * @param t Pointer to store the absolute time
 */
void hrt_store_absolute_time(volatile hrt_abstime *t);

/**
 * @brief Initialize the HRT subsystem
 * 
 * This must be called once during system initialization before using any other HRT functions.
 * It initializes the microsecond timer and internal data structures.
 */
void hrt_init(void);

/**
 * @brief Initialize a callout structure
 * 
 * This must be called before using a hrt_call structure for the first time.
 * 
 * @param entry Pointer to the callout structure to initialize
 */
void hrt_call_init(hrt_call_t *entry);

/**
 * @brief Schedule a one-shot callback after a delay
 * 
 * Schedules callout(arg) to be called after the specified delay.
 * If the entry is already scheduled, it will be rescheduled with the new parameters.
 * 
 * @param entry Pointer to the callout structure (must be initialized with hrt_call_init)
 * @param delay Delay in microseconds before calling the callback
 * @param callout Callback function to call (can be NULL for timeout testing)
 * @param arg User argument to pass to the callback
 */
void hrt_call_after(hrt_call_t *entry, hrt_abstime delay, hrt_callout callout, void *arg);

/**
 * @brief Schedule a callback at an absolute time
 * 
 * Schedules callout(arg) to be called at the specified absolute time.
 * If the time has already passed, the callback will be called immediately.
 * 
 * @param entry Pointer to the callout structure (must be initialized with hrt_call_init)
 * @param calltime Absolute time in microseconds when to call the callback
 * @param callout Callback function to call (can be NULL for timeout testing)
 * @param arg User argument to pass to the callback
 */
void hrt_call_at(hrt_call_t *entry, hrt_abstime calltime, hrt_callout callout, void *arg);

/**
 * @brief Schedule a periodic callback
 * 
 * Schedules callout(arg) to be called after delay, and then repeatedly every interval.
 * The interval is measured between scheduled times, not actual execution times,
 * so the call rate may jitter but should not drift.
 * 
 * @param entry Pointer to the callout structure (must be initialized with hrt_call_init)
 * @param delay Initial delay in microseconds before first callback
 * @param interval Period in microseconds between subsequent callbacks
 * @param callout Callback function to call
 * @param arg User argument to pass to the callback
 */
void hrt_call_every(hrt_call_t *entry, hrt_abstime delay, hrt_abstime interval, 
                    hrt_callout callout, void *arg);

/**
 * @brief Cancel a scheduled callback
 * 
 * Removes the entry from the callout list. If the callback is currently executing,
 * this function will wait for it to complete.
 * 
 * @param entry Pointer to the callout structure to cancel
 */
void hrt_cancel(hrt_call_t *entry);

/**
 * @brief Check if a callout has been invoked
 * 
 * @param entry Pointer to the callout structure to check
 * @return true if the entry has been invoked and removed from the callout list,
 *         or if it was never scheduled. Always returns false for repeating callouts.
 */
bool hrt_called(hrt_call_t *entry);

#ifdef __cplusplus
}
#endif

